package com.shiguiwu.springmybatis.javabase.thread;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @description: 下面我们来模仿有100个人同时访问，并且每个人对咱们的网站发起10次请求，最后总访问次数应该是1000次。实现访问如下。
 * @author: stone
 * @date: Created by 2021/7/1 22:38
 * @version: 1.0.0
 * @pakeage: com.shiguiwu.springmybatis.thread
 */
@Slf4j
public class CASTests {
    public static int count = 0;

    //访问次数
    static AtomicInteger countV2 = new AtomicInteger();

    public static void main(String[] args) throws InterruptedException {
//        testV1();
        testV2();
    }

    /**
     * 不加锁有并发问题
     * 请求一百所需的要时间是155，count=959
     * @throws InterruptedException
     */
    public static void requestV1() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(5);
        count++;
    }

    /**
     * 加锁
     * 请求一百所需的要时间是5797，count=1000
     * @throws InterruptedException
     */
    public synchronized static void requestV2() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(5);
        count++;
    }


    /**
     *
     * @throws InterruptedException
     * 请求一百所需的要时间是145，count=1000
     */
    public  static void requestV3() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(5);
        int expectCount = 0;
        do {
            expectCount = getCount();
        } while (!compareAndSwap(expectCount, expectCount + 1));
    }

    /**
     * 100个人请求10个所需的要时间是141，countV2=1000
     * @throws InterruptedException
     */
    public static void requestV4() throws InterruptedException{
        TimeUnit.MILLISECONDS.sleep(5);
        countV2.incrementAndGet();
    }

    public synchronized static boolean compareAndSwap(int expectCount, int newCount) {
        //判断count当前值是否和期望的expectCount一样，如果一样将newCount赋值给count
        if (expectCount == getCount()) {
            count = newCount;
            return true;
        }
        return false;

    }

    private static int getCount() {
        return count;
    }


    //请求一百所需的要时间是155，count=959
    public static void testV1() throws InterruptedException {
        int threadSize = 100;
        CountDownLatch countDownLatch = new CountDownLatch(threadSize);

        long start = System.currentTimeMillis();
        for (int i = 0; i < threadSize; i++) {

            new Thread(() -> {
                try {
                    for (int j = 0; j < 10; j++) {
                        requestV3();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch.countDown();

                }
            }).start();
        }

        countDownLatch.await();
        log.error("100个人请求10个所需的要时间是{}，count={}", (System.currentTimeMillis() - start), count);

    }

    public static void testV2() throws InterruptedException {
        int threadSize = 100;
        CountDownLatch countDownLatch = new CountDownLatch(threadSize);

        long start = System.currentTimeMillis();
        for (int i = 0; i < threadSize; i++) {

            new Thread(() -> {
                try {
                    for (int j = 0; j < 10; j++) {
                        requestV4();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch.countDown();

                }
            }).start();
        }

        countDownLatch.await();
        log.error("100个人请求10个所需的要时间是{}，countV2={}", (System.currentTimeMillis() - start), countV2);

    }


}
